#include "MessageQueue.h"
#include "Trace.h"

using namespace std;

namespace tsc
{
namespace common
{

MessageQueue* MessageQueue::mInstance = 0;

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
MessageQueue::MessageQueue()
  : mServerHandler(0),
    mApplicationHandler(0)
{
  mInQueue.clear();
  mOutQueue.clear();
  mTimerQueue.clear();
} // MessageQueue::MessageQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
MessageQueue::~MessageQueue()
{
  Message* pMessage = 0;
  list<Message*>::iterator iter;

  for(iter = mInQueue.begin(); iter != mInQueue.end(); iter++)
  {
    pMessage = *iter;
    if(pMessage)
    {
      TRACE_ERROR(STR("MessageQueue::~MessageQueue removing IN queue message Id=0x%08X",
                      pMessage->getId()));
      delete pMessage;
    }
  }
  mInQueue.clear();

  for(iter = mOutQueue.begin(); iter != mOutQueue.end(); iter++)
  {
    pMessage = *iter;
    if (pMessage)
    {
      TRACE_ERROR(STR("MessageQueue::~MessageQueue removing OUT queue message Id=0x%08X",
                      pMessage->getId()));
      delete pMessage;
    }
  }
  mOutQueue.clear();

  for(iter = mTimerQueue.begin(); iter != mTimerQueue.end(); iter++)
  {
    pMessage = *iter;
    if (pMessage)
    {
      TRACE_ERROR(STR("MessageQueue::~MessageQueue removing TIMER queue message Id=0x%08X",
                      pMessage->getId()));
      delete pMessage;
    }
  }
  mTimerQueue.clear();

} // MessageQueue::~MessageQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
MessageQueue* MessageQueue::instance()
{
  if (!mInstance)
  {
    mInstance = new MessageQueue;
  }

  return mInstance;
} // MessageQueue::instance

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
void MessageQueue::registerServerHandler(RequestHandler* aHandler)
{
  mServerHandler = aHandler;
}

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
void MessageQueue::registerApplicationHandler(RequestHandler* aHandler)
{
  mApplicationHandler = aHandler;
}

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
void MessageQueue::toInQueue(Message*& aMessage)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);
  mInQueue.push_back(aMessage);
  aMessage = 0;
} // MessageQueue::toInQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
void MessageQueue::toOutQueue(Message*& aMessage)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);
  mOutQueue.push_back(aMessage);
  aMessage = 0;
} // MessageQueue::toOutQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
void MessageQueue::toTimerQueue(Message*& aMessage)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);
  mTimerQueue.push_back(aMessage);
  aMessage = 0;
} // MessageQueue::toTimerQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
bool MessageQueue::fromInQueue(Message*& aMessage)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);
  if(mInQueue.empty())
  {
    aMessage = 0;
    return false;
  }
  else
  {
    aMessage = mInQueue.front();
    mInQueue.pop_front();
    return true;
  }
} // MessageQueue::fromInQueue


/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
bool MessageQueue::fromInQueue(Message*& aMessage, unsigned int aConnectionId)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);

  list<Message*>::iterator iter;
  Message* pMessage;

  if(mInQueue.empty())
  {
    aMessage = 0;
    return false;
  }
  else
  {
    for(iter = mInQueue.begin(); iter != mInQueue.end(); iter++)
    {
      pMessage = *iter;
      if(pMessage->getConnectionId() == aConnectionId)
      {
        aMessage = pMessage;
        mInQueue.erase(iter);
        return true;
      }
    }
    aMessage = 0;
    return false;
  }
} // MessageQueue::fromInQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
bool MessageQueue::fromOutQueue(Message*& aMessage)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);
  if(mOutQueue.empty())
  {
    aMessage = 0;
    return false;
  }
  else
  {
    aMessage = mOutQueue.front();
    mOutQueue.pop_front();
    return true;
  }
} // MessageQueue::fromOutQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
bool MessageQueue::fromOutQueue(Message*& aMessage, unsigned int aConnectionId)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);

  list<Message*>::iterator iter;
  Message* pMessage;

  if(mOutQueue.empty())
  {
    aMessage = 0;
    return false;
  }
  else
  {
    for(iter = mOutQueue.begin(); iter != mOutQueue.end(); iter++)
    {
      pMessage = *iter;
      if(pMessage->getConnectionId() == aConnectionId)
      {
        aMessage = pMessage;
        mInQueue.erase(iter);
        return true;
      }
    }
    aMessage = 0;
    return false;
  }
} // MessageQueue::fromOutQueue

/*******************************************************************************
 *
 *
 *
 ******************************************************************************/
bool MessageQueue::fromTimerQueue(Message*& aMessage, unsigned int aTimerId)
{
  boost::unique_lock<boost::mutex> scoped_lock(mMutex);

  list<Message*>::iterator iter;
  Message* pMessage;

  if(mTimerQueue.empty())
  {
    aMessage = 0;
    return false;
  }
  else
  {
    for(iter = mTimerQueue.begin(); iter != mTimerQueue.end(); iter++)
    {
      pMessage = *iter;
      if(pMessage->getId() == aTimerId)
      {
        aMessage = pMessage;
        mInQueue.erase(iter);
        return true;
      }
    }
    aMessage = 0;
    return false;
  }
} // MessageQueue::fromTimerQueue

} // namespace common
} // namespace tsc
